#!/usr/bin/env bash

set -euo pipefail

# Test that src and dest trees are as identical as bup is capable of
# making them.  For now, use rsync -niaHAX ...

usage() {
cat <<EOF
Usage:
   compare-trees [-c] [-x] [--] SOURCE DEST
   compare-trees --features
   compare-trees -h
OPTIONS:
  -h
    Display help
  -c
    Check file content (default)
  -x
    Don't check file content (rely on size/timestamps, etc.)
  --times
  --no-times
    Check or don't check timestamps (checking is the default)
  --features
    Show enabled features
  --
    Don't treat following arguments as options (e.g. compare-trees -- -c dest)
EOF
}

show_features=''
verify_content=" --checksum"
verify_times=' --times'

case "$#/${1:-}" in
    1/-h) usage; exit 0;;
    1/--features) show_features=yes; shift;;
    *)
        while test $# -gt 0; do
            case "$1" in
                -h|--features) usage 1>&2; exit 2;;
                -c) verify_content=" --checksum"; shift;;
                -x) verify_content=""; shift;;
                --times) verify_times=' --times'; shift;;
                --no-times) verify_times=''; shift;;
                --) shift; break;;
                [^-]*) break;;
            esac
        done
esac

if test $# -ne 2 -a -z "$show_features"; then
    usage 1>&2
    exit 2
fi

src="${1:-}"
dest="${2:-}"

rsync_opts="-rlpgoD" # --archive, without --times
rsync_opts="$rsync_opts -niH --delete"
rsync_opts="$rsync_opts$verify_content"
rsync_opts="$rsync_opts$verify_times"

comparing_acls=''
rsync_version=$(rsync --version)
if [[ ! "$rsync_version" =~ "ACLs" ]] || [[ "$rsync_version" =~ "no ACLs" ]]; then
    echo "Not comparing ACLs (not supported by available rsync)" 1>&2
else
    case "$OSTYPE" in
        cygwin|darwin|netbsd)
            echo "Not comparing ACLs (not yet supported on $OSTYPE)" 1>&2
            ;;
        *)
            comparing_acls=yes
            rsync_opts="$rsync_opts -A"
            ;;
    esac
fi

xattrs_available=''
if [[ ! "$rsync_version" =~ "xattrs" ]] || [[ "$rsync_version" =~ "no xattrs" ]]; then
    echo "Not comparing xattrs (not supported by available rsync)" 1>&2
else
    xattrs_available=yes
fi

if test "$show_features"; then
    echo "POSIX ACLs: ${comparing_acls:-no}"
    echo "Extended attributes (xattrs): ${xattrs_available:-no}"
fi

if test "$show_features"; then
    exit 0
fi

tmpfile="$(mktemp /tmp/bup-test-XXXXXXX)" || exit $?
trap "rm -rf '$tmpfile'" EXIT || exit $?

# Even in dry-run mode, rsync may fail if -X is specified and the
# filesystems don't support xattrs.

if test "$xattrs_available"; then
    rsync $rsync_opts -X "$src" "$dest" > "$tmpfile"
    if test $? -ne 0; then
        # Try again without -X
        rsync $rsync_opts "$src" "$dest" > "$tmpfile" || exit $?
    fi
else
    rsync $rsync_opts "$src" "$dest" > "$tmpfile" || exit $?
fi

if test $(wc -l < "$tmpfile") != 0; then
    echo "Differences between $src and $dest" 1>&2
    cat "$tmpfile"
    exit 1
fi

exit 0
